home *** CD-ROM | disk | FTP | other *** search
- /*
- File: TThread.h
-
- Contains: xxx put contents here xxx
-
- Written by: Tim Harnett
-
- Copyright: © 1994 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <18> 2/17/95 TMH fixed a oops re16 got nuked
- <15> 2/7/95 TMH added userinterrupt stuff
- <14> 2/6/95 TMH redid CEventQueue using CLinkedList
- <12> 12/20/94 TMH fix bug so we don't overflow event queue
- <11> 12/12/94 TMH added of thread events
- <10> 11/17/94 TMH increased wakeupthread stack size
- <9> 11/11/94 TMH fixed TWakeupThread::Busy() to look at IO state
- <8> 11/10/94 TMH use StopForIO
- <7> 11/8/94 TMH added fIdentifierTag
- <6> 10/28/94 TMH added gAppTaskRef and StartThreadFromCompletionRoutine
- <5> 10/26/94 TMH added GetThreadA5
- <4> 10/25/94 TMH added TWakeupThread
- <3> 10/11/94 TMH added StopThread, StartThread
- <2> 10/6/94 TMH added TApplicationThread
- <1> 9/21/94 TMH seperated from Application.cp
- 9/21/94 TMH xxx put comment here xxx
-
- To Do:
- */
-
-
- #ifndef __TThread__
- #define __TThread__
-
- #ifndef __THREADS__
- #include "Threads.h"
- #endif
-
- #ifndef __Debug__
- #include "Debug.h"
- #endif
-
- #ifndef __CLinkedList__
- #include "CLinkedList.h"
- #endif
-
-
- class CThreadEventQueue;
- class CThreadEvent;
- class TCooperativeThread;
-
- const Boolean kAllowDuplicateEvent = true;
- const Boolean kDontAllowDuplicateEvent = false;
-
-
- //---------------------------------------
- // C T h r e a d E v e n t Q u e u e
- //----------------------------------------
-
- class CThreadEvent : public CLink {
- public:
- CThreadEvent() {
- fEventID = 0;
- fEventData0 = 0;
- fEventData1 = 0;
- fEventData2 = 0;
- };
-
- CThreadEvent(OSType eventID,long eventData0=0,long eventData1=0,long eventData2=0)
- {
- fEventID = eventID;
- fEventData0 = eventData0;
- fEventData1 = eventData1;
- fEventData2 = eventData2;
- };
-
- long fEventID;
- long fEventData0;
- long fEventData1;
- long fEventData2;
-
- long EventID() { return fEventID; };
- long EventData0() { return fEventData0; };
- long EventData1() { return fEventData1; };
- long EventData2() { return fEventData2; };
-
- };
-
- //---------------------------------------
- // C T h r e a d E v e n t Q u e u e
- //----------------------------------------
-
- #define kMaxThreadEvents 16
-
-
- class CThreadEventQueue {
- friend class CThreadEventIterator;
- friend class TCooperativeThread;
-
- public:
- CThreadEventQueue();
-
- void Insert(CThreadEvent& threadEvent);
- void Remove(CThreadEvent& threadEvent);
- void FlushEvents(long eventID);
- long EventCount() { return fEvents.Count(); }
-
- private:
- void CopyNextEvent(CThreadEvent& threadEvent);
-
- CLinkedList fEvents;
-
- CLinkedList fAvail;
-
- CThreadEvent fEventBufs[kMaxThreadEvents]; // this is how we allocate event buffers.
- };
-
-
-
-
- //-----------------------------------------------
- // T C o o p e r a t i v e T h r e a d
- //-----------------------------------------------
-
- // This is abstract base class. You have to subclass it to get
- // a thread.
-
- #define kDefaultThreadStackSize 6000
- #define kNoCreationOptions 0
-
- // Additional options we define -- we use the upper bits of ThreadOptions
- #define kNeedEventQueue (1<<31)
-
-
- enum ThreadIOState {
- sThreadIOIdle = 100, // we want these number to not conflict with Threads.h definitions.
- sThreadStoppedForIO
- };
-
-
- class TCooperativeThread {
- friend class CThreadEventIterator;
- public:
- TCooperativeThread();
- ~TCooperativeThread();
- void ICooperativeThread(OSType tag, Size stackSize=kDefaultThreadStackSize,ThreadOptions createOptions=kNoCreationOptions,long wneSleep=10);
-
- virtual void* ThreadMain() = 0; // you have to define this.
- static pascal void* __ThreadMain(void* inParam);
-
- long GetWNESleep() { return fWNESleep; };
-
- //-------------------
- // State Management
- //-------------------
-
-
- ThreadState GetThreadState();
- OSErr StartThread() { return(SetThreadState(fThreadID, kReadyThreadState, kApplicationThreadID)); }
- void StartThreadFromCompletionRoutine() { ::SetThreadReadyGivenTaskRef(gAppTaskRef,fThreadID); };
- OSErr StopThread() { return(SetThreadState(fThreadID, kStoppedThreadState, kApplicationThreadID)); }
- void StopForIO();
-
- Boolean IsStopped() { return this->GetThreadState() == kStoppedThreadState; };
-
- //-------------------
- // Task switching
- //------------------
-
-
- static pascal void SwitchInProc ( ThreadID threadBeingSwitched, void* switchProcParam );
- static pascal void SwitchOutProc ( ThreadID threadBeingSwitched, void* switchProcParam );
- void Yield(TCooperativeThread* threadToRun=0);
-
-
- //-------------------
- // Event Queue
- //-------------------
-
-
- OSErr QueueEvent(CThreadEvent& threadEvent);
- OSErr PostEvent(long eventID, long eventData=0, Boolean allowDuplicate=kAllowDuplicateEvent);
- OSErr PostEvent(CThreadEvent& theEvent, Boolean allowDuplicate=kAllowDuplicateEvent);
-
- void FlushEvents(long eventID) { fEventQueue->FlushEvents(eventID); };
- CThreadEvent* WaitNextEvent();
- CThreadEvent* GetNextEvent();
- CThreadEvent* EventAvail();
-
- OSType UserInterrupt() { return fUserInterrupt; };
- Boolean HasUserInterrupted() { return fUserInterrupt != 0; };
- void SetUserInterrupt(OSType interruptID) { ASSERT(fUserInterrupt==0); fUserInterrupt = interruptID; }
- void ClearUserInterrupt() { fUserInterrupt = 0; }
-
-
-
- //-------------------
- // Accessors
- //------------------
-
- long GetThreadA5() { return fA5; };
-
- protected:
- long fWNESleep;
- ThreadID fThreadID;
- OSType fIdentifierTag; // so we can see what thread is which in the debugger
-
- ThreadIOState fThreadIOState;
- void* fOutParam;
-
- OSType fUserInterrupt;
-
- void* fSavedTopHandler;
- long fA5;
-
- static ThreadTaskRef gAppTaskRef; // this is the same for all threads, set by TApplicationThread.
-
- static unsigned long gDebugCallCount; // this is for debugging, remove it later
-
- CThreadEventQueue* fEventQueue;
- CLinkedList* EventList() { return &fEventQueue->fEvents; }
-
- };
-
-
- //-----------------------------------------
- // C T h r e a d E v e n t I t e r a t o r
- //------------------------------------------
-
-
- class CThreadEventIterator : public CLinkedListIterator {
- public:
- CThreadEventIterator(CThreadEventQueue* eventQueue) : CLinkedListIterator( &eventQueue->fEvents ) {}
- CThreadEventIterator(TCooperativeThread* thread) : CLinkedListIterator( thread->EventList() ) {}
- CThreadEvent* FirstEvent() { return (CThreadEvent*) CLinkedListIterator::FirstItem(); }
- CThreadEvent* NextEvent() { return (CThreadEvent*) CLinkedListIterator::NextItem(); };
- void FlushCurrentEvent() { CLinkedListIterator::UnlinkCurrentItem(); }
- };
-
-
- //-----------------------------------------------
- // T A p p l i c a t i o n T h r e a d
- //-----------------------------------------------
-
-
- // The Application thread is "special" it is automatically created by the
- // Thread Manager. We however need a Thread object so we can do neat stuff
-
-
- class TApplicationThread : public TCooperativeThread {
- public:
- TApplicationThread() {};
-
- void IApplicationThread();
- virtual void* ThreadMain(); // Override. Hit Wall. Never Called!
-
- };
-
-
-
-
- //---------------------------------
- // T W a k e u p T h r e a d
- // Thread used for ASynchronous IO
- // See develop Issue 17.
- //---------------------------------
-
- #define kWakeupThreadStacksize 6000
-
- class TWakeupThread : public TCooperativeThread {
- public:
- TWakeupThread();
- void IWakeupThread();
- virtual void* ThreadMain();
-
- void SetThreadToWake(TCooperativeThread* threadToWake) { fThreadToWake = threadToWake; };
- Boolean Busy() { return fThreadToWake != 0 ? fThreadToWake->GetThreadState() == sThreadStoppedForIO : false; };
- private:
- TCooperativeThread* fThreadToWake;
-
- };
-
-
-
-
-
-
-
- #endif __TThread__